/*
 * readers-writers-n-m-problem.c
 *
 *  Created on: Apr 15, 2010
 *      Authors: guilherme
 * 				 matheus
 */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

void* readerf(void*);
void* writerf(void*);

sem_t semaforo;		
int nr = 0;		// número de processos lendo
int nw = 0;		// número de processos escrevendo
int write_request = 0; // número de processos querendo escrever

int main(int argc, char *argv[])
{
	   int id; // Número pelo qual o semáforo é reconhecido pelo programa
	   int i;
	   int n,m; // Numero de Readers e Writers, respectivamente
	   n = *argv[argc-2]-48;
       m = *argv[argc-1]-48;
       
       //printf("%d %d\n",n,m);
       
       pthread_t reader[n]; // threads reader
       pthread_t writer[m]; // threads writer
       
       sem_init (&semaforo,0,1);
       
       for (i = 0; i < n; i++)
       {
       		if(pthread_create(&reader[i], 0, readerf, &i))
       		{
            	perror("Leitor nao criado!");
            	exit(1);							
       	 	}         
       }
       
       for (i = 0; i < m; i++)
       {
       		if(pthread_create(&writer[i], 0, writerf, &i))
       		{
            	perror("Escritor nao criado!");
            	exit(1);							
       	 	}  
       }
       for (i = 0; i < n; i++)
       {
               pthread_join(reader[i], NULL);
       }
       for (i = 0; i < m; i++)
       {
               pthread_join(writer[i], NULL);
       }

	   sem_destroy(&semaforo);
       return EXIT_SUCCESS;
}

void* readerf(void*arg)			
{
   	int i = *(int*)arg;
   
    int can_read;
    while(1){
        can_read = 1;

        sem_wait(&semaforo);
        if(nw == 0)  
        	nr++;
        else                               
        	can_read = 0;
        sem_post(&semaforo);

        if(can_read) {
            printf("Leitor %d esta lendo... %d writers %d readers\n",i,nw,nr);
			sleep(0.5);
            sem_wait(&semaforo);
            nr--;
            sem_post(&semaforo);
        }

        sched_yield();
    }
    return 0;
}

void* writerf(void*arg)		
{
	int i = *(int*)arg;
    int can_write;
    while(1){
        can_write = 1;

        sem_wait (&semaforo);
        if(nr == 0 && nw == 0)   
        	nw++;
        else          
        { 
        	can_write = 0; 
        }
        sem_post(&semaforo);

        if(can_write) 
        {
            printf("Escritor %d está escrevendo... %d writers %d readers\n",i,nw,nr);

            sleep(0.5);

            sem_wait(&semaforo);
            nw--;
            sem_post(&semaforo);
        }

        sched_yield();
    }
    return 0;
}

